////////////////////////////////////////////////////////////////////////////////
//  COPYRIGHT (C) 2010 TELECOM DIGITAL MEDIA ("TDMEDIA").
//  ALL RIGHTS RESERVED.
//
//  THIS IS CONFIDENTIAL AND PROPRIETARY INTELLECTUAL PROPERTY OWNED BY AND
//  CREATED ON BEHALF OF TDMEDIA. ANY FORM OF DISTRIBUTION, COPY,
//  MODIFICATION WITHOUT THE WRITTEN CONSENT FROM TDMEDIA IS STRICTLY
//  PROHIBITED.
////////////////////////////////////////////////////////////////////////////////
package cc.telecomdigital.tdstock;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * useful part to deal with string.
 * 
 * @author haibo
 */

public class StringUtils
{
	// private static final String TAG = StringUtils.class.getSimpleName();
	public enum ITDLNumber
	{
		STOCKPRICE, NET, NETPERCENTAGE, TURNOVER, LOTSIZE, HIGHTLOW
	};

	public static final int		TOTAL_LENGTH_ON_STOCKPRICE	= 5;
	private static NumberFormat	_formaterOnSacle			= DecimalFormat
																	.getInstance();

	private static String		DOLLAR_REPLACEMENT			= "zzzdollarzzz";				// for
																							// $
	public static String		SLASH_REPLACEMENT			= "zzzslashzzz";				// \\

	private static NumberFormat	formaterOnSacle0			= DecimalFormat.getInstance();
	private static NumberFormat	formaterOnSacle1			= DecimalFormat.getInstance();
	private static NumberFormat	formaterOnSacle2			= DecimalFormat.getInstance();
	private static NumberFormat	formaterOnSacle3			= DecimalFormat.getInstance();
	private static NumberFormat	formaterOnSacle4			= DecimalFormat.getInstance();

	public static String inputStreamToString(final InputStream stream)
			throws IOException
	{
		BufferedReader br = new BufferedReader(new InputStreamReader(stream)/*
																			 * ,
																			 * 16
																			 * *
																			 * 1024
																			 */);
		StringBuilder sb = new StringBuilder(/* 16 * 1024 */);
		String line = null;
		while ((line = br.readLine()) != null)
		{
			sb.append(line + "\n");
		}
		br.close();
		return sb.toString();
	}

	public static String formatString(final String source,
			final String prefix, final String suffix)
	{
		StringBuffer resultBuffer = new StringBuffer();
		if (prefix != null && source.indexOf(prefix) != 0)
		{
			resultBuffer.append(prefix);
		}
		if (source != null)
		{
			resultBuffer.append(source);
		}
		if (suffix != null && source.indexOf(suffix) != 0)
		{
			resultBuffer.append(suffix);
		}
		return resultBuffer.toString();

	}

	public static String join(Collection<?> items, String delimiter)
	{
		if (items == null || items.isEmpty())
		{
			return "";
		}

		final Iterator<?> iter = items.iterator();
		final StringBuilder buffer = new StringBuilder(iter.next().toString());

		while (iter.hasNext())
		{
			buffer.append(delimiter).append(iter.next());
		}

		return buffer.toString();
	}

	public static String FormatNumber(ITDLNumber type, final String source)
	{
		String result = null;
		if (source == null || source.equals(""))
		{
			return type == ITDLNumber.NETPERCENTAGE ? "0.00%" : "0.000";
		}

		// TDStockLog.d(TAG, "::FormatNumber, type=" + type.name() + "-> value="
		// + source);

		if (type == ITDLNumber.LOTSIZE || type == ITDLNumber.TURNOVER)
		{
			try
			{
				double value = Double.parseDouble(source);
				_formaterOnSacle.setMaximumFractionDigits(1);
				_formaterOnSacle.setMinimumFractionDigits(1);
				if (value < 1000.0d)
				{
					result = new StringBuffer(_formaterOnSacle
							.format(value)).append("K").toString();
				}
				else if (value > 1000.d && value < 1000 * 1000)
					result = new StringBuffer(_formaterOnSacle
							.format(value / 1000.0d)).append("M")
							.toString();
				else if (value >= 1000 * 1000)
				{
					result = new StringBuffer(_formaterOnSacle
							.format(value / 1000000.0d)).append("B")
							.toString();
				}

			}
			catch (NumberFormatException e)
			{
				// e.printStackTrace();
				result = source;
			}

		}
		else if (type == ITDLNumber.STOCKPRICE)
		{
			try
			{
				double price = Double.parseDouble(source);
				if (price >= 1000d)
				{
					return source;
				}

				// if(Math.abs(price) <= 0.000001d){
				//					
				// return CommonDefn.DEFAULT_FIELD_VALUE2;
				// }

				int intLen = source.indexOf(".");
				int decimalLen = TOTAL_LENGTH_ON_STOCKPRICE - intLen - 1;
				_formaterOnSacle.setMaximumFractionDigits(decimalLen);
				_formaterOnSacle.setMinimumFractionDigits(decimalLen);
				result = _formaterOnSacle.format(price);

			}
			catch (NumberFormatException e)
			{
				// e.printStackTrace();
				result = source;
			}

		} // 处理週高和週低默认值 从 0.000 为 ---
		else if (type == ITDLNumber.HIGHTLOW)
		{

			try
			{
				double price = Double.parseDouble(source);

				if (price >= 1000d)
				{
					return source;
				}

				if (Math.abs(price) <= 0.000001d)
				{

					return CommonDefn.DEFAULT_FIELD_VALUE2;
				}

				int intLen = source.indexOf(".");
				int decimalLen = TOTAL_LENGTH_ON_STOCKPRICE - intLen - 1;
				_formaterOnSacle.setMaximumFractionDigits(decimalLen);
				_formaterOnSacle.setMinimumFractionDigits(decimalLen);
				result = _formaterOnSacle.format(price);

			}
			catch (NumberFormatException e)
			{
				// e.printStackTrace();
				result = source;
			}

		}
		else if (type == ITDLNumber.NET)
		{
			try
			{
				double net = Double.parseDouble(source);
				int intLen = source.indexOf(".");

				if (source.indexOf("-") < 0)
				{
					int decimalLen = TOTAL_LENGTH_ON_STOCKPRICE - intLen
							- 1;
					_formaterOnSacle.setMaximumFractionDigits(decimalLen);
					_formaterOnSacle.setMinimumFractionDigits(decimalLen);
					result = new StringBuffer("+").append(
							_formaterOnSacle.format(net)).toString();
				}
				else
				{
					int decimalLen = TOTAL_LENGTH_ON_STOCKPRICE - intLen; // include
																			// sign
																			// already;
					_formaterOnSacle.setMaximumFractionDigits(decimalLen);
					_formaterOnSacle.setMinimumFractionDigits(decimalLen);
					result = _formaterOnSacle.format(net);
				}

			}
			catch (NumberFormatException e)
			{
				// TDStockLog.d("StringUtils", "source=" + source);
				// e.printStackTrace();
				result = source;
			}

		}
		else if (type == ITDLNumber.NETPERCENTAGE)
		{

			try
			{
				double netPercentage = Double.parseDouble(source);
				_formaterOnSacle.setMaximumFractionDigits(2);
				_formaterOnSacle.setMinimumFractionDigits(2);
				if (source.indexOf("-") < 0)
				{
					result = new StringBuffer("+").append(
							_formaterOnSacle.format(netPercentage))
							.append("%").toString();
				}
				else result = new StringBuffer(_formaterOnSacle
							.format(netPercentage)).append("%")
							.toString();
			}
			catch (NumberFormatException e)
			{
				// e.printStackTrace();
				result = "0.00%";
			}

		}

		return result;
	}

	/**
	 * FormatNumber XX.XXXX X.XXXX
	 * 
	 * @param source
	 * @param n
	 * @return
	 */
	public static String FormatNumberToFour(String source, int n)
	{
		if (source == "--")
			return source;
		int size = source.length();
		int pix = source.indexOf(".");
		int index = size - 1 - pix;
		if (pix == -1)
			return source + ".0000";
		if (index == n)
			return source;
		if (index > n)
			return source.substring(0, pix + n + 1);
		String tmp = "";
		for (int i = 0; i < (n - index); i++)
		{
			tmp = tmp + "0";
		}
		return source + tmp;
	}

	public static String FormatNumberOnTurnOverOrShareTraded(String source)
	{
		String result = null;
		if (source == null || source.equals(""))
		{
			return result;
		}
		_formaterOnSacle.setMaximumFractionDigits(1);
		_formaterOnSacle.setMinimumFractionDigits(1);
		double value = 0.0d;
		try
		{
			value = Double.parseDouble(source);
			value = value * 1000.0d; // restore to the original value
			if (value < 1000)
			{
				result = _formaterOnSacle.format(value).toString();
			}
			else if (value >= 1000 && value < 1000 * 1000)
			{
				result = new StringBuffer(_formaterOnSacle
						.format(value / 1000.0d)).append(
						CommonDefn.UNIT_K).toString();
			}
			else if (value >= 1000 * 1000 && value < 1000 * 1000 * 1000)
			{
				result = new StringBuffer(_formaterOnSacle.format(value
						/ (1000.0d * 1000.0d))).append(CommonDefn.UNIT_M)
						.toString();
			}
			else
			{
				result = new StringBuffer(_formaterOnSacle.format(value
						/ (1000.0d * 1000.0d * 1000.0d))).append(
						CommonDefn.UNIT_B).toString();
			}
		}
		catch (NumberFormatException e)
		{
			// e.printStackTrace();
		}
		return result;
	}

	public static String centerStringWithStaticLength(String source,
			String fillChar, int totalLength)
	{
		StringBuffer result = new StringBuffer(source);
		if (source != null && source.length() < totalLength)
		{
			int fillLength = totalLength - source.length();
			int fillLeft = fillLength / 2;
			int fillRight = fillLength - fillLeft;
			for (int index = 0; index < fillLeft; index++)
			{
				result.insert(0, fillChar);
			}
			for (int index = 0; index < fillRight; index++)
			{
				result.append(fillChar);
			}
		}

		return result.toString();
	}

	/**
	 * @param source
	 * @param fillChar
	 * @param totalLength
	 * @param isFillLeft
	 *            true: fill left / false : fill the right
	 * @return
	 */
	public static String fillStringToStaticLength(String source,
			String fillChar, int totalLength, boolean isFillLeft)
	{
		StringBuffer result = new StringBuffer();
		if (source != null && source.length() < totalLength)
		{
			result.append(source);
			int fillLength = totalLength - source.length();
			int fillLeft = isFillLeft ? fillLength : 0;
			int fillRight = isFillLeft ? 0 : fillLength;
			for (int index = 0; index < fillLeft; index++)
			{
				result.insert(0, fillChar);
			}
			for (int index = 0; index < fillRight; index++)
			{
				result.append(fillChar);
			}
		}
		else if (source != null)
		{
			result.append(source);
		}

		return result.toString();
	}

	public static String quoStr(String source)
	{
		StringBuffer tmp = new StringBuffer();
		tmp.append("\"");
		tmp.append(source == null ? "" : source);
		tmp.append("\"");
		return tmp.toString();
	}

	// DT, 2011/01/14, format a numeric value with a specified number of decimal
	// place
	// rounding is performed automatically
	public static String formatToDp(double dvalue, int dp)
	{
		String result = null;

		// disable thousands-separators
		_formaterOnSacle.setGroupingUsed(false);

		// set the number of digits after decimal point
		_formaterOnSacle.setMaximumFractionDigits(dp);
		_formaterOnSacle.setMinimumFractionDigits(dp);

		result = _formaterOnSacle.format(dvalue);

		return result;
	}

	// DT, 2011/01/14, format a numeric value with a specified number of decimal
	// place
	// rounding is performed automatically
	public static String formatToDp(String source, int dp)
	{
		String result = null;

		try
		{
			double dvalue = Double.parseDouble(source);

			result = formatToDp(dvalue, dp);

		}
		catch (Exception e)
		{
			result = "";
		}

		return result;
	}

	// DT, 2011/01/17, format a numeric value to either one format with
	// specified number of decimal place
	// depends on whether the value is greater than or equal to a pre-defined
	// value
	public static String formatToEitherDp(double dvalue, double lowerLimit,
			double upperLimit, int dp1, int dp2)
	{
		String result = null;

		// disable thousands-separators
		_formaterOnSacle.setGroupingUsed(false);

		if (dvalue <= lowerLimit || dvalue >= upperLimit)
		{
			// set the number of digits after decimal point
			_formaterOnSacle.setMaximumFractionDigits(dp2);
			_formaterOnSacle.setMinimumFractionDigits(dp2);
		}
		else
		{
			// set the number of digits after decimal point
			_formaterOnSacle.setMaximumFractionDigits(dp1);
			_formaterOnSacle.setMinimumFractionDigits(dp1);
		}

		result = _formaterOnSacle.format(dvalue);

		return result;
	}

	// DT, 2011/01/17, format a numeric value to either one format with
	// specified number of decimal place
	// depends on whether the value is within pre-defined lower limit and upper
	// limit
	public static String formatToEitherDp(String source, double lowerLimit,
			double upperLimit, int dp1, int dp2)
	{
		String result = null;

		try
		{
			double dvalue = Double.parseDouble(source);

			result = formatToEitherDp(dvalue, lowerLimit, upperLimit, dp1,
					dp2);

		}
		catch (Exception e)
		{
			result = "";
		}

		return result;
	}

	// DT, 2011/02/01, format a numeric value to follow 5 chars rule,
	// maximum length of formatted numeric value is 5 characters,
	// including plus sign or minus sign, decimal place
	public static String formatToFiveCharsRule(String source)
	{
		boolean negative = false;
		String result = null;

		// prepare formatter with 0, 1, 2 d.p. respectively
		NumberFormat formaterOnSacle0 = DecimalFormat.getInstance();
		NumberFormat formaterOnSacle1 = DecimalFormat.getInstance();
		NumberFormat formaterOnSacle2 = DecimalFormat.getInstance();

		// disable thousands-separators
		formaterOnSacle0.setGroupingUsed(false);
		formaterOnSacle1.setGroupingUsed(false);
		formaterOnSacle2.setGroupingUsed(false);

		// set the number of digits after decimal point
		formaterOnSacle0.setMaximumFractionDigits(0);
		formaterOnSacle0.setMinimumFractionDigits(0);

		formaterOnSacle1.setMaximumFractionDigits(1);
		formaterOnSacle1.setMinimumFractionDigits(1);

		formaterOnSacle2.setMaximumFractionDigits(2);
		formaterOnSacle2.setMinimumFractionDigits(2);

		try
		{
			double dvalue = Double.parseDouble(source);

			// check value is positive or negative, remove negative sign first
			if (dvalue == 0.0000)
			{
				negative = false;

				// special handling for possible -0.0000 case,
				// assign 0.0000 to overwrite original -0.0000
				dvalue = 0.0000;
			}
			else
			{
				if (dvalue < 0.0000)
				{
					negative = true;
					dvalue = dvalue * -1;
				}
				else
				{
					negative = false;
				}
			}

			// format to corresponding d.p. according to value range
			if (dvalue >= 100.0000)
			{
				result = formaterOnSacle0.format(dvalue);

			}
			else if (dvalue >= 10.0000 && dvalue <= 99.9999)
			{
				result = formaterOnSacle1.format(dvalue);

			}
			else if (dvalue >= 0.0000 && dvalue <= 9.9999)
			{
				result = formaterOnSacle2.format(dvalue);
			}

			// special handling for possible +100.0 case
			// remove trailing .0
			if (result.endsWith(".0") && (result.length() == 5))
			{
				result = result.substring(0, result.length() - 2);
			}

			// add back plus sign or minus sign
			if (dvalue == 0.0000)
			{
				result = "+" + result;
			}
			else
			{
				if (negative == true)
				{
					result = "-" + result;
				}
				else
				{
					result = "+" + result;
				}
			}

		}
		catch (Exception e)
		{
			result = "";
		}

		return result;
	}

	// DT, 2011/03/31, format a positive numeric value to follow 6 chars rule,
	// maximum length of formatted numeric value is 6 characters,
	// including decimal point, without plus sign
	public static String formatToSixCharsRuleWithoutSign(String source)
	{
		String result = null;

		// ---------modidified by haibo, 2011-08-03, improve
		// performance-----------

		// prepare formatter with 0, 1, 2, 3, 4 d.p. respectively
		/*
		 * NumberFormat formaterOnSacle0 = DecimalFormat.getInstance();
		 * NumberFormat formaterOnSacle1 = DecimalFormat.getInstance();
		 * NumberFormat formaterOnSacle2 = DecimalFormat.getInstance();
		 * NumberFormat formaterOnSacle3 = DecimalFormat.getInstance();
		 * NumberFormat formaterOnSacle4 = DecimalFormat.getInstance();
		 */

		// ---------modidified by haibo, 2011-08-03, improve
		// performance-----------

		// disable thousands-separators
		formaterOnSacle0.setGroupingUsed(false);
		formaterOnSacle1.setGroupingUsed(false);
		formaterOnSacle2.setGroupingUsed(false);
		formaterOnSacle3.setGroupingUsed(false);
		formaterOnSacle4.setGroupingUsed(false);

		// set the number of digits after decimal point
		formaterOnSacle0.setMaximumFractionDigits(0);
		formaterOnSacle0.setMinimumFractionDigits(0);

		formaterOnSacle1.setMaximumFractionDigits(1);
		formaterOnSacle1.setMinimumFractionDigits(1);

		formaterOnSacle2.setMaximumFractionDigits(2);
		formaterOnSacle2.setMinimumFractionDigits(2);

		formaterOnSacle3.setMaximumFractionDigits(3);
		formaterOnSacle3.setMinimumFractionDigits(3);

		formaterOnSacle4.setMaximumFractionDigits(4);
		formaterOnSacle4.setMinimumFractionDigits(4);

		try
		{
			double dvalue = Double.parseDouble(source);

			// format to corresponding d.p. according to value range
			if (dvalue >= 10000.0000)
			{
				result = formaterOnSacle0.format(dvalue);

			}
			else if (dvalue >= 1000.0000 && dvalue <= 9999.9999)
			{
				result = formaterOnSacle1.format(dvalue);

			}
			else if (dvalue >= 100.0000 && dvalue <= 999.9999)
			{
				result = formaterOnSacle2.format(dvalue);

			}
			else if (dvalue >= 10.0000 && dvalue <= 99.9999)
			{
				result = formaterOnSacle3.format(dvalue);

			}
			else if (dvalue >= 0.0000 && dvalue <= 9.9999)
			{
				result = formaterOnSacle4.format(dvalue);

			}

			// special handling for possible 10000.0 case
			// remove trailing .0
			if (result.endsWith(".0") && (result.length() == 7))
			{
				result = result.substring(0, result.length() - 2);
			}

		}
		catch (Exception e)
		{
			result = "";
		}

		return result;
	}

	/**
	 * @param source
	 * @return true : contain Chinese character
	 */
	public static boolean isChineseCharacterExist(String source)
	{
		int length = source.length();
		byte[] b;
		for (int i = 0; i < length; i++)
		{
			b = source.substring(i).getBytes();
			if ((b[0] & 0xff) > 128)
				return true;
		}
		return false;
	}

	/**
	 * @param stream
	 * @param keyEntry
	 *            (i.e. abc, 123,456)
	 * @return
	 */
	public static Map<String, String> streamToMap(final InputStream stream,
			final String keyEntry)
	{
		HashMap<String, String> map = new HashMap<String, String>();
		try
		{
			String sourceContent = inputStreamToString(stream);
			String[] entrySet = keyEntry.split("[,，]");
			for (String key : entrySet)
			{
				String tagBegin = "<" + key + ">";
				String tagEnd = "</" + key + ">";

				int start = sourceContent.indexOf(tagBegin);
				int end = sourceContent.indexOf(tagEnd);
				if (start >= 0 && end >= 0 && end > start)
				{
					map.put(key, sourceContent.substring(start
							+ tagBegin.length(), end));
				}
			}
		}
		catch (Exception e)
		{

		}

		return map;
	}

	/**
	 * @param stream
	 * @param keyEntry
	 *            (i.e. abc, 123,456)
	 * @return
	 */
	public static Map<String, String> stringToMap(final String sourceContent,
			final String keyEntry)
	{
		HashMap<String, String> map = new HashMap<String, String>();
		try
		{
			String[] entrySet = keyEntry.split("[,，]");
			for (String key : entrySet)
			{
				String tagBegin = "<" + key + ">";
				String tagEnd = "</" + key + ">";

				int start = sourceContent.indexOf(tagBegin);
				int end = sourceContent.indexOf(tagEnd);
				if (start >= 0 && end >= 0 && end > start)
				{
					map.put(key, sourceContent.substring(start
							+ tagBegin.length(), end));
				}
			}
		}
		catch (Exception e)
		{

		}

		return map;
	}

	/*
	 * by dan
	 */
	// DT, 2011/02/01, format a positive numeric value to follow 5 chars rule,
	// maximum length of formatted numeric value is 5 characters,
	// including decimal point, without plus sign
	public static String formatToFiveCharsRuleWithoutSign(String source)
	{
		final String DECIMAL_POINT = ".";
		final String ZERO = "0";

		String result = null;

		// ---------modidified by haibo, 2011-08-03, improve
		// performance-----------
		// prepare formatter with 0, 1, 2, 3 d.p. respectively
		/*
		 * NumberFormat formaterOnSacle0 = DecimalFormat.getInstance();
		 * NumberFormat formaterOnSacle1 = DecimalFormat.getInstance();
		 * NumberFormat formaterOnSacle2 = DecimalFormat.getInstance();
		 * NumberFormat formaterOnSacle3 = DecimalFormat.getInstance();
		 */
		// ---------modidified by haibo, 2011-08-03, improve
		// performance-----------

		// disable thousands-separators
		formaterOnSacle0.setGroupingUsed(false);
		formaterOnSacle1.setGroupingUsed(false);
		formaterOnSacle2.setGroupingUsed(false);
		formaterOnSacle3.setGroupingUsed(false);

		// set the number of digits after decimal point
		formaterOnSacle0.setMaximumFractionDigits(0);
		formaterOnSacle0.setMinimumFractionDigits(0);

		formaterOnSacle1.setMaximumFractionDigits(1);
		formaterOnSacle1.setMinimumFractionDigits(1);

		formaterOnSacle2.setMaximumFractionDigits(2);
		formaterOnSacle2.setMinimumFractionDigits(2);

		formaterOnSacle3.setMaximumFractionDigits(3);
		formaterOnSacle3.setMinimumFractionDigits(3);

		try
		{
			double dvalue = Double.parseDouble(source);

			// format to corresponding d.p. according to value range
			if (dvalue >= 1000.0000)
			{
				result = formaterOnSacle0.format(dvalue);

			}
			else if (dvalue >= 100.0000 && dvalue <= 999.9999)
			{
				result = formaterOnSacle1.format(dvalue);

			}
			else if (dvalue >= 10.0000 && dvalue <= 99.9999)
			{
				result = formaterOnSacle2.format(dvalue);

			}
			else if (dvalue >= 0.0000 && dvalue <= 9.9999)
			{
				result = formaterOnSacle3.format(dvalue);

			}

			// special handling for possible 1000.0 case
			// remove trailing .0
			if (result.endsWith(".0") && (result.length() == 6))
			{
				result = result.substring(0, result.length() - 2);
			}

			// remove trailer zeroes for values with decimal point
			// logic: keep removing "0" from the end until it is a non-zero
			// character
			if (result.indexOf(DECIMAL_POINT) != -1)
			{
				while (result.lastIndexOf(ZERO) == result.length() - 1)
				{
					result = result.substring(0, result.length() - 1);
				}

				// add back a zero after decimal point if it is non-zero value
				if (result.lastIndexOf(DECIMAL_POINT) == result.length() - 1)
				{
					if (result.equals("0."))
					{
						result = "0";
					}
					else
					{
						result = result + ZERO;
					}
				}
			}

		}
		catch (Exception e)
		{
			result = "";
		}

		return result;
	}

	public static String formatNumberByUsingTruncate(NumberFormat nf, double value, int fractionDigits)
	{
		String result = "";
		if (nf == null)
					nf = NumberFormat.getInstance();
		nf.setGroupingUsed(false);
		nf.setMaximumFractionDigits(fractionDigits + 1);
		nf.setMinimumFractionDigits(fractionDigits + 1);
		result = nf.format(value).substring(0, nf.format(value).length() - 1);
		return result;
	}

	/*
	 * =================round down number by
	 * ouyangzhihui(zor)20110729==================
	 */

	/**
	 * format net 國內指數，e.g: 香港，
	 * 
	 * @param tmp
	 * @return 值大於10則取整數，否則保留4位數(整數+小數點+小數)
	 */
	public static String formatNumberByNetIndex(String tmp)
	{
		try
		{
			String pix = tmp.substring(0, 1);
			tmp = StringUtils.roundDownFormatToNCharsRule(tmp, 4);
			if (Double.parseDouble(tmp) >= 10)
			{
				tmp = roundDownInteger(tmp);
			}
			if (!tmp.endsWith("-"))
			{
				if (!StringUtils.F.equals(pix))
				{
					pix = StringUtils.Z;
				}
				tmp = pix + tmp;
			}
			else
			{
				tmp = "--";
			}
		}
		catch (Exception e)
		{
			return "--";
		}
		return tmp;
	}

	/**
	 * format net 國際指數，e.g: 亞洲，歐美(延遲)
	 * 
	 * @param tmp
	 * @return 保留4位數(整數+小數點+小數)
	 */
	public static String formatNumberByNetWorldIndex(String tmp)
	{
		String pix = tmp.substring(0, 1);
		tmp = StringUtils.roundDownFormatToNCharsRule(tmp, 4);
		if (!tmp.endsWith("-"))
		{
			if (!StringUtils.F.equals(pix))
			{
				pix = StringUtils.Z;
			}
			tmp = pix + tmp;
		}
		else
		{
			tmp = "--";
		}
		return tmp;
	}

	/**
	 * format net （支持TOP20）
	 * 
	 * @param tmp
	 * @return 保留5位數(整數+小數點+小數)
	 */
	public static String formatNumberByNet(String tmp)
	{
		if (tmp == null || tmp.length() < 1)
		{
			return "--";
		}

		String pix = tmp.substring(0, 1);
		tmp = StringUtils.roundDownFormatToFiveCharsRule(tmp);
		if (!tmp.endsWith("-"))
		{
			if (!StringUtils.F.equals(pix))
			{
				pix = StringUtils.Z;
			}
			tmp = pix + tmp;
		}
		else
		{
			tmp = "--";
		}
		return tmp;
	}

	/**
	 * format net perectage
	 * 
	 * @param tmp
	 * @param n
	 *            總共位數
	 * @return 保留N位數(整數+小數點+小數)不包括 % 號
	 */
	public static String formatNumberByNetPerectage(String tmp, int n)
	{
		if (tmp == null || tmp.length() < 1)
		{
			return "--";
		}

		String pix = tmp.substring(0, 1);
		tmp = StringUtils.roundDownFormatToNCharsRule(tmp, n);
		if (!tmp.endsWith("-"))
		{
			if (!StringUtils.F.equals(pix))
			{
				pix = StringUtils.Z;
			}
			tmp = pix + tmp + "%";
		}
		else
		{
			tmp = "--";
		}
		return tmp;
	}

	/**
	 * format turnove
	 * 
	 * @param tmp
	 *            以 K 为单位的浮点数字符串
	 * @param n
	 *            小数点后几位
	 * @return 返回帶單位(K/M/B)的保留N位小數的浮點數
	 */
	public static String formatNumberByTurnove(String tmp, int n)
	{
		if (tmp == null || tmp.length() < 1)
		{
			return "--";
		}
		Double fieldValue = Double.parseDouble(tmp);
		if (fieldValue < 1000)
		{
			tmp = StringUtils.roundDownFormatToAutoCharsRuleCutByIsAllZero(String.valueOf(fieldValue), n, false);
			tmp += CommonDefn.UNIT_K;
		}
		else if (fieldValue >= 1000 && fieldValue < 1000 * 1000)
		{
			tmp = StringUtils.roundDownFormatToAutoCharsRuleCutByIsAllZero(String.valueOf(fieldValue / 1000.0d), n, false);
			tmp += CommonDefn.UNIT_M;
		}
		else if (fieldValue >= 1000 * 1000)
		{
			tmp = StringUtils.roundDownFormatToAutoCharsRuleCutByIsAllZero(String.valueOf(fieldValue / 1000000.0d), n, false);
			tmp += CommonDefn.UNIT_B;
		}
		return tmp;
	}

	/**
	 * format turnove
	 * 
	 * @param tmp
	 *            以 K 为单位的浮点数字符串
	 * @param n
	 *            小数点后几位
	 * @return 返回帶單位(K/M/B)的保留N位小數的浮點數
	 */
	public static String formatNumberByTurnove2(String tmp, int n)
	{
		if (tmp == null || tmp.length() < 1)
		{
			return "--";
		}
		Double fieldValue = Double.parseDouble(tmp);
		if (fieldValue < 1000)
		{
			tmp = StringUtils.roundDownFormatToAutoCharsRuleCutByIsAllZero(String.valueOf(fieldValue), n, false);
		}
		else if (fieldValue >= 1000 && fieldValue < 1000 * 1000)
		{
			tmp = StringUtils.roundDownFormatToAutoCharsRuleCutByIsAllZero(String.valueOf(fieldValue / 1000.0d), n, false);
			tmp += CommonDefn.UNIT_K;
		}
		else if (fieldValue >= 1000 * 1000 && fieldValue < 1000 * 1000 * 1000)
		{
			tmp = StringUtils.roundDownFormatToAutoCharsRuleCutByIsAllZero(String.valueOf(fieldValue / 1000000.0d), n, false);
			tmp += CommonDefn.UNIT_M;
		}
		else if (fieldValue >= 1000 * 1000 * 1000)
		{
			tmp = StringUtils.roundDownFormatToAutoCharsRuleCutByIsAllZero(String.valueOf(fieldValue / 1000000000.0d), n, false);
			tmp += CommonDefn.UNIT_B;
		}
		return tmp;
	}

	/*
	 * =================round down number by
	 * ouyangzhihui(zor)20110726==================
	 */
	public static final String	Z			= "+";
	public static final String	F			= "-";
	public static final String	EN_CHARS	= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

	/**
	 * 整數部分+小數部分+小數點，總共位數為5位
	 * 
	 * @param tmp
	 * @return
	 */
	public static String roundDownFormatToFiveCharsRule(String tmp)
	{
		return roundDownFormatToNCharsRule(tmp, 5);
	}

	/**
	 * 整數部分+小數部分+小數點，總共位數為6位
	 * 
	 * @param tmp
	 * @return
	 */
	public static String roundDownFormatToSixCharsRule(String tmp)
	{
		return roundDownFormatToNCharsRule(tmp, 6);
	}

	/**
	 * 最多位数多少位，不足不补零
	 * 
	 * @param tmp
	 * @param n
	 * @return
	 */
	public static String roundDownFormatToNCharsRuleNotAddZero(String tmp, int n)
	{
		/* ********************************* */
		// 處理 empty
		if (tmp == null || "".equals(tmp))
		{
			return "";
		}
		// 處理非數字
		try
		{
			Double.parseDouble(tmp);
		}
		catch (NumberFormatException e)
		{
			return tmp;
		}
		// 處理 正/負號
		String pix = tmp.substring(0, 1);
		if (F.equals(pix) || Z.equals(pix))
		{
			tmp = tmp.substring(1);
		}
		/* ********************************* */

		int index = tmp.indexOf(".");
		int length = tmp.length();
		if (length >= n)
		{
			tmp = tmp.substring(0, n);
			if (tmp.endsWith("."))
				tmp = tmp.substring(0, tmp.length() - 1);
		}
		/*
		 * else { int c = n - length; if (index >= 0) { for (int i = 0; i < c;
		 * i++) { tmp += "0"; } } else { c--; for (int i = 0; i < c; i++) { if
		 * (i == 0) { tmp += "."; } tmp += "0"; } } }
		 */
		return tmp;
	}

	/**
	 * 整數部分+小數部分+小數點，總共位數為N
	 * 
	 * @param tmp
	 *            要處理的數值
	 * @param n
	 *            數據中長度
	 * @return 處理完的數值
	 */
	public static String roundDownFormatToNCharsRule(String tmp, int n)
	{
		/* ********************************* */
		// 處理 empty
		if (tmp == null || "".equals(tmp))
		{
			return "";
		}
		// 處理非數字
		try
		{
			Double.parseDouble(tmp);
		}
		catch (NumberFormatException e)
		{
			return tmp;
		}
		// 處理 正/負號
		String pix = tmp.substring(0, 1);
		if (F.equals(pix) || Z.equals(pix))
		{
			tmp = tmp.substring(1);
		}
		/* ********************************* */

		int index = tmp.indexOf(".");
		int length = tmp.length();
		if (length >= n)
		{
			tmp = tmp.substring(0, n);
			if (tmp.endsWith("."))
				tmp = tmp.substring(0, tmp.length() - 1);
		}
		else
		{
			int c = n - length;
			if (index >= 0)
			{
				for (int i = 0; i < c; i++)
				{
					tmp += "0";
				}
			}
			else
			{
				c--;

				for (int i = 0; i < c; i++)
				{
					if (i == 0)
					{
						tmp += ".";
					}
					tmp += "0";
				}
			}
		}
		return tmp;
	}

	/**
	 * 保留小数点后几位，並是否補全小數位數
	 * 
	 * @param tmp
	 *            要處理的數值
	 * @param n
	 *            保留小數點後幾位
	 * @param isAddZero
	 *            小數位數不足，是否用0補全
	 * @return 處理完的數值
	 */
	public static String roundDownFormatToAutoCharsRule(String tmp, int n, boolean isAddZero)
	{
		return roundDownFormatToAutoCharsRule(tmp, n, isAddZero, false);
	}

	/**
	 * 保留小数点后几位，小數位數不夠補零，小數點後全是零時是否截除只保留整數
	 * 
	 * @param tmp
	 *            要處理的數值
	 * @param n
	 *            保留小數點後幾位
	 * @param isAllZeroCut
	 *            小數點後全為0時，是否去掉小數點只取整
	 * @return 處理完的數值
	 */
	public static String roundDownFormatToAutoCharsRuleCutByIsAllZero(String tmp, int n, boolean isAllZeroCut)
	{
		return roundDownFormatToAutoCharsRule(tmp, n, true, isAllZeroCut);
	}

	/**
	 * 保留小数点后几位，小數位數不夠補零，小數點後全是零時只保留整數
	 * 
	 * @param tmp
	 *            要處理的數值
	 * @param n
	 *            保留小數點後幾位
	 * @return 處理完的數值
	 */
	public static String roundDownFormatToAutoCharsRuleCutAllZero(String tmp, int n)
	{
		return roundDownFormatToAutoCharsRule(tmp, n, true, true);
	}

	/**
	 * 保留小数点后几位，並是否補全小數位數，是否小數位數全是 0 時，只取整
	 * 
	 * @param tmp
	 *            要處理的數值
	 * @param n
	 *            保留小數點後幾位
	 * @param isAddZero
	 *            小數位數不足，是否用0補全
	 * @param isAllZeroCut
	 *            小數點後全為0時，是否去掉小數點只取整
	 * @return 處理完的數值
	 */
	public static String roundDownFormatToAutoCharsRule(String tmp, int n, boolean isAddZero, boolean isAllZeroCut)
	{
		/* ********************************* */
		// 處理 empty
		if (tmp == null || "".equals(tmp))
		{
			return "";
		}
		// 處理非數字
		try
		{
			Double.parseDouble(tmp);
		}
		catch (NumberFormatException e)
		{
			return tmp;
		}
		// 處理 正/負號
		String pix = tmp.substring(0, 1);
		if (F.equals(pix) || Z.equals(pix))
		{
			tmp = tmp.substring(1);
		}
		/* ********************************* */

		int index = tmp.indexOf(".");
		if (index >= 0) // 有小數點
		{
			int last = tmp.length();
			int c = last - index - 1; // 小數點後位數

			// 如果小數點後位數大於等於要保留數
			if (c >= n)
			{
				tmp = tmp.substring(0, index + 1 + n); // 直接截取
			}
			// 補全零
			if (isAddZero)
			{
				for (int i = 0; i < n - c; i++)
				{
					tmp += "0";
				}
			}
			// 如果小數點後全是零
			if (isAllZeroCut)
			{
				// 判断小数点后是否全是零
				String t = "";
				for (int i = 0; i < n; i++)
				{
					t += "0";
				}
				String str = tmp.substring(index + 1);
				// System.out.println(str+" , "+t);
				if (t.equals(str)) // 如果小数点后全是零
				{
					tmp = tmp.substring(0, index);
				}
			}
		}
		else if (isAddZero && !isAllZeroCut) // 如果没有小数点要补全，并不截掉后面全是零的小数。
		{
			tmp += ".";
			for (int i = 0; i < n; i++)
			{
				tmp += "0";
			}
		}
		return tmp;
	}

	/**
	 * 取整数，并整数位数 tmp=123456.7890, n=5 tmp=12345.6000, n=5 e.g: 12345
	 * tmp=1234.5600, n=5 e.g: 1234
	 * 
	 * @param tmp
	 *            要處理的數值
	 * @param n
	 *            最多不超過取整數位數 (不限制时传值-1)
	 * @return 處理完的數值
	 */
	public static String roundDownNCharsInteger(String tmp, int n)
	{
		/* ********************************* */
		// 處理 empty
		if (tmp == null || "".equals(tmp))
		{
			return "";
		}
		// 處理非數字
		try
		{
			Double.parseDouble(tmp);
		}
		catch (NumberFormatException e)
		{
			return tmp;
		}
		// 處理 正/負號
		String pix = tmp.substring(0, 1);
		if (F.equals(pix) || Z.equals(pix))
		{
			tmp = tmp.substring(1);
		}
		/* ********************************* */

		int index = tmp.indexOf(".");
		if (index >= 0) // 去除小数点
		{
			tmp = tmp.substring(0, index);
		}
		// e.g
		if (tmp.length() > n && n != -1)
		{
			tmp = tmp.substring(0, n);
		}
		return tmp;
	}

	/**
	 * 只取整數
	 * 
	 * @param tmp
	 * @return
	 */
	public static String roundDownInteger(String tmp)
	{
		return roundDownNCharsInteger(tmp, -1);
	}

	/**
	 * 四舍五入取整
	 * 
	 * @param num
	 * @return
	 */
	public static String formatScaleInteger(double num)
	{
		BigDecimal b = new BigDecimal(num);
		num = b.setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue();
		return String.valueOf((long) num);
	}

	/* ================================================================= */

	public static String replaceAllCtLfWithBR(String source)
	{
		String result = source;
		try
		{

			StringBuffer buffer = new StringBuffer();

			// replace the special char
			for (int index = 0; index < source.length(); index++)
			{
				if (source.charAt(index) == '$')
				{
					buffer.append(DOLLAR_REPLACEMENT);
				}
				else if (source.charAt(index) == '\\')
				{
					buffer.append(SLASH_REPLACEMENT);
				}
				else if (source.charAt(index) == '\n' || source.charAt(index) == '\r')
				{
					buffer.append(SLASH_REPLACEMENT + "n");
				}
				else
				{
					buffer.append(source.charAt(index));
				}
			}
			// replace the special char

			result = buffer.toString().replaceAll(SLASH_REPLACEMENT + "n", "<br>").replaceAll(SLASH_REPLACEMENT + "r", "<br>");

			// restore the replace
			result = result.replaceAll(SLASH_REPLACEMENT, "\\").replaceAll(DOLLAR_REPLACEMENT, "$");
			// restore the replace;

		}
		catch (Exception e)
		{

		}
		return result;
	}

	public static final String	ENCODING_POST[]	= { "%25", "%22", "%20", "%21", "%23", "%24", "%26", "%27", "%28", "%29", "%2A", "%2B", "%2C", "%2D", "%2E", "%2F", "%3A", "%3B", "%3C", "%3D", "%3E", "%3F", "%40", "%5B",
			"%5C", " %5D", "%5E", "%5F", "%60"	};

	public static final char	ENCODING_CHAR[]	= { '%', '\"', ' ', '!', '#', '$', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`' };

	// to avoid java.lang.IllegalArgumentException in UrlEncode
	public static String preUrlEncode(final String resource)
	{

		StringBuffer buff = new StringBuffer();
		try
		{

			HashMap<Integer, String> pos_value = new HashMap<Integer, String>();
			int item = 0;
			for (char c : ENCODING_CHAR)
			{

				for (int index = 0; index < resource.length(); index++)
				{
					if (resource.charAt(index) == c)
					{
						pos_value.put(index, ENCODING_POST[item]);
					}
				}
				item++;
			}

			for (int index = 0; index < resource.length(); index++)
			{
				if (pos_value.containsKey(index))
				{
					buff.append(pos_value.get(index));
				}
				else buff.append(resource.charAt(index));
			}

		}
		catch (Exception e)
		{
		}
		return buff.toString();
	}

	public static String safeUrlEncode(String resource)
	{
		String result = preUrlEncode(resource);
		result = URLEncoder.encode(result);
		return result;
	}

	public static String formatRoundUpByNetPercetageNumber(double num)
	{
		DecimalFormat fnum = new DecimalFormat("##0.00");
		return fnum.format(num);
	}

	/**
	 * 半角转换为全角
	 * 
	 * @param input
	 * @return
	 */
	public static String ToDBC(String input)
	{
		char[] c = input.toCharArray();
		for (int i = 0; i < c.length; i++)
		{
			if (c[i] == 12288)
			{
				c[i] = (char) 32;
				continue;
			}
			if (c[i] > 65280 && c[i] < 65375)
						c[i] = (char) (c[i] - 65248);
		}
		return new String(c);
	}
}
